import { create } from 'zustand'
import { persist, createJSONStorage } from 'zustand/middleware'

import type { ApiUser, ApiTokenResponse } from '../types'

type AuthState = {
  accessToken: string | null
  refreshToken: string | null
  user: ApiUser | null
  setTokens: (tokens: Partial<ApiTokenResponse | { access_token: string; refresh_token: string }>) => void
  setUser: (user: ApiUser | null) => void
  setRemember: (remember: boolean) => void
  logout: () => void
}

export const useAuthStore = create<AuthState>()(
  persist(
    (set) => ({
      accessToken: null,
      refreshToken: null,
      user: null,
      setTokens: (tokens) =>
        set((state) => ({
          accessToken: tokens.access_token ?? state.accessToken,
          refreshToken: tokens.refresh_token ?? state.refreshToken,
        })),
      setUser: (user) => set({ user }),
      setRemember: (remember: boolean) => {
        try {
          localStorage.setItem('love-notes-remember', remember ? 'true' : 'false')
        } catch {}
      },
      logout: () => set({ accessToken: null, refreshToken: null, user: null }),
    }),
    {
      name: 'love-notes-auth',
      storage: createJSONStorage(() => {
        const storage = {
          getItem: (name: string) => {
            try {
              return sessionStorage.getItem(name) ?? localStorage.getItem(name)
            } catch {
              return null
            }
          },
          setItem: (name: string, value: string) => {
            try {
              const remember = localStorage.getItem('love-notes-remember') === 'true'
              const target = remember ? localStorage : sessionStorage
              const other = remember ? sessionStorage : localStorage
              target.setItem(name, value)
              try { other.removeItem(name) } catch {}
            } catch {}
          },
          removeItem: (name: string) => {
            try { localStorage.removeItem(name) } catch {}
            try { sessionStorage.removeItem(name) } catch {}
          },
        }
        return storage as unknown as Storage
      }),
      partialize: (state) => ({
        accessToken: state.accessToken,
        refreshToken: state.refreshToken,
        user: state.user,
      }),
    },
  ),
)
